/*
 *  Copyright 2008 Mark Ashworth <javameme@gmail.com>.
 *
 *  Licensed under the GNU General Public License v3 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.gnu.org/licenses/gpl-3.0.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package xperiment.metaphor.model.entity;

import metaphor.service.ServiceException;
import xperiment.metaphor.model.*;
import xperiment.metaphor.model.contact.Address;

import javax.persistence.*;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Organization
 *
 * @author Mark Ashworth
 * @version 1.0.0
 * @since 1.0.0
 */
public class Organization extends DomainObject implements Named, Persistent, XML {

    /** An empty organization object */
    public static final Organization EMPTY = new Organization();

    /* The unique database id for the object */
	@Id @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "organization_id", unique = true, nullable = false)
    private Long id;

    /** The organization's name */
    @Column(name="organization_name", unique=false, nullable=true)
	private String name;

    /** The entity information of the organization. */
    @OneToOne
    @JoinColumn(name="entity")
    private xperiment.metaphor.model.entity.Entity entity = new xperiment.metaphor.model.entity.Entity();

    /** The list of companies in an organization */
    private SortedSet<Company> companies = new TreeSet<Company>();

     /** Enabled */
    @Column(name="enabled", unique=false, nullable=true)
    private boolean enabled = true;

    /**
     * Default constructor
     */
    public Organization() {
        super();
    }
    /**
     * Creates the organization with the name
     * @param name The organization's name
     */
    public Organization(String name) {
        super();
        this.name = name;
    }

    public Long getId() {
        return id;
    }
    
    
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    
    /**
     * Adds a company
     * @param company The company to add
     */
    public void add(Company company) {
        this.companies.add(company);
    }
    /**
     * Returns the list of companies of the organization
     * @return SortedSet<Company>
     */
    public SortedSet<Company> getCompanies() {
        if (this.companies == null) {
            this.companies = new TreeSet<Company>();
        }
        return companies;
    }

    public void setCompanies(SortedSet<Company> companies) {
        SortedSet<Company> old = getCompanies();
        this.companies = companies;
        firePropertyChange("companies", old, this.companies);
    }

    /**
     * Returns the entity information of this organization
     * @return Entity
     */
    protected xperiment.metaphor.model.entity.Entity getEntity() {
        if (this.entity == null) {
            this.entity = new xperiment.metaphor.model.entity.Entity();
        }
        return this.entity;
    }

    /**
     * Gets the organizations's telephone number
     * @return String
     */
    public String getTelephoneNo() {
        return this.getEntity().getContactInformation().getTelephoneNo();
    }

    /**
     * Gets the organizations's cellphone number
     * @return String
     */
    public String getCellphoneNo() {
        return this.getEntity().getContactInformation().getCellphoneNo();
    }

    /**
     * Gets the organizations's facsimile number
     * @return String
     */
    public String getFacsimile() {
        return this.getEntity().getContactInformation().getFacsimileNo();
    }

    /**
     * Gets the organizations's email
     * @return String
     */
    public String getEmail() {
        return this.getEntity().getContactInformation().getEmail();
    }

    /**
     * Gets the organizations's postal address
     * @return Address
     */
    public Address getPostalAddress() {
        return this.getEntity().getContactInformation().getPostalAddress();
    }

    /**
     * Gets the organizations's physical address
     * @return Address
     */
    public Address getPhysicalAddress() {
        return this.getEntity().getContactInformation().getPhysicalAddress();
    }

    /**
     * Whether the person is enabled or active in the system
     * @return boolean
     */
    public boolean isEnabled() {
		return enabled;
	}

    /**
     * Whether the person is enabled or active in the system
     * @param enabled The new value
     */
	public void setEnabled(boolean enabled) {
		boolean old = this.enabled;
		this.enabled = enabled;
		firePropertyChange("enabled", old, this.enabled);
	}

    /**
     * Returns the XML representation of the organization.<br />
     * @return String
     */
    public String toXML() {

        return "<organization='" + getClass().getName()
                + "' id='" + getId()
                + "</organization>";
    }

    /**
     * Saves the organization to the persistent store
     * @return Organization
     * @throws xperiment.metaphor.model.ModelException If there was an error
     */
    public Organization save() throws ModelException {

        /*
         * Save the companies
         */
        for (Company company : getCompanies()) {
            company.attach(getApplicationManager());
            company.save();
        }

        try {
            this.entity = (xperiment.metaphor.model.entity.Entity) getDao().persist(this.entity);

            Organization o = (Organization) getDao().persist(this);
            this.id = o.getId();

            return this;
        } catch (ServiceException e) {
            throw new SaveException("Unable to save organization", e);
        }
    }

    /**
     * Sets the organization's name
     * @param name The new value
     * @return Organization
     */
    public Organization name(String name) {
        this.setName(name);
        return this;
    }

    /**
     * Sets the organization's telephone number
     * @param telephoneNo The new value
     * @return Organization
     */
    public Organization telephone(String telephoneNo) {
        this.getEntity().getContactInformation().setTelephoneNo(telephoneNo);
        return this;
    }

    /**
     * Sets the organization's cellphone number
     * @param cellphoneNo The new value
     * @return Organization
     */
    public Organization cellphone(String cellphoneNo) {
        this.getEntity().getContactInformation().setCellphoneNo(cellphoneNo);
        return this;
    }

    /**
     * Sets the organization's facsimile number
     * @param facsimileNo The new value
     * @return Organization
     */
    public Organization facsimile(String facsimileNo) {
        this.getEntity().getContactInformation().setFacsimileNo(facsimileNo);
        return this;
    }

    /**
     * Sets the organization's email
     * @param email The new value
     * @return Organization
     */
    public Organization email(String email) {
        this.getEntity().getContactInformation().setEmail(email);
        return this;
    }

    /**
     * Sets the organization's postal address
     * @param postalAddress The new value
     * @return Organization
     */
    public Organization postalAddress(Address postalAddress) {
        this.getEntity().getContactInformation().setPostalAddress(postalAddress);
        return this;
    }

    /**
     * Sets the organization's physical address
     * @param physicalAddress The new value
     * @return Organization
     */
    public Organization physicalAddress(Address physicalAddress) {
        this.getEntity().getContactInformation().setPhysicalAddress(physicalAddress);
        return this;
    }

    /**
     * Adds a new company
     * @return Company
     */
    public Company addCompany() {
        return addCompany(null);
    }

    /**
     * Adds a new company
     * @param name The name of the company
     * @return Company
     */
    public Company addCompany(String name) {
        Company company = new Company(name);
        this.getCompanies().add(company);
        return company;
    }
}
